package com.demo.server.impl;

import com.common.Dto.CompanyIpoDTO;
import com.common.Dto.CompanyLoginDTO;
import com.common.Dto.CompanyRegisterDTO;
import com.common.LO.*;
import com.common.VO.CompanyLoginVo;
import com.common.VO.IpoVO;
import com.common.VO.RegisterVO;
import com.common.commont.Messageconstant;
import com.common.commont.contractAddress;
import com.common.result.Result;
import com.demo.mapper.*;
import com.demo.server.CompanyServer;
import com.tools.Fisco.CompanyInfo;
import com.tools.Fisco.UserInfo;
import com.tools.Fisco.context.context;
import com.tools.Fisco_tools.CompanyGoesTGtable_tools;
import com.tools.Fisco_tools.CompanyInfo_tools;
import com.tools.Fisco_tools.EquityStructureTable_tools;
import com.tools.Fisco_tools.UserInfo_tools;
import com.tools.untils.Create_;
import lombok.extern.slf4j.Slf4j;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Set;

@Service
@Slf4j
public class CompanyServerImpl implements CompanyServer {
    @Autowired
    UserMapper userMapper;


    @Autowired
    CompanyMapper companyMapper;

    @Autowired
    CompanyGoesMapper companyGoesMapper;
    @Autowired
    EquityStructureMapper equityStructureMapper;
    @Autowired
    pendingStockOrdersMapper pendingStockOrdersMapper;
    /**
     * 注册公司账号
     * @param companyRegisterDTO
     * @return
     */
     @Override
    public Result<RegisterVO> Register(CompanyRegisterDTO companyRegisterDTO) {
        UserInformationLO UserInformation = UserInformationLO.builder()
                .id(context.getCurrtId())
                .build();
        UserInformation = userMapper.select_user(UserInformation);
        if (
               ! (UserInformation.getPassword().equals(Create_.create_hash256(UserInformation.getAccountAddress()+companyRegisterDTO.getUser_password())) &&
                         UserInformation.getAccount().equals(companyRegisterDTO.getUser_account()) &&
                         UserInformation.getCard().equals(companyRegisterDTO.getUser_card()) &&
                         UserInformation.getId().equals(context.getCurrtId()))
        )
        {
            return Result.error(Messageconstant.Information_Verification_Failed);
        }
        FiscoLO fiscoSdk = Create_.create_fisco_sdk(UserInformation.getAccountPrivatekey());
        try {
            UserInfo.Struct0 select = UserInfo_tools.select(UserInfo.load(contractAddress.InfoAddress, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair()), context.getCurrtId());
            if(
                    !(
                            select.account.equals(companyRegisterDTO.getUser_account())  &&
                                    select.card.equals(companyRegisterDTO.getUser_card()) &&
                                    select.password.equals(Create_.create_hash256(UserInformation.getAccountAddress()+companyRegisterDTO.getUser_password())) &&
                                    select.id.equals(context.getCurrtId())
                    )
            ){
                throw new ContractException(Messageconstant.NOSynchronization);
            }
        } catch (ContractException e) {
            throw new RuntimeException(e);
        }
       //资料核验没有问题,开始准备创建用户



         if (UserInformation.getPayPassword() == null){
             return Result.error(Messageconstant.No_payAccount);
         }else if(UserInformation.getAccountRole() == 2){
          //2.查看注册公司的用户旗下是不是有公司了
             return Result.error(Messageconstant.Have_company);
         }else if( companyMapper.select_number(CompanyInformationLO.builder().name(companyRegisterDTO.getName()).build()) != 0){
         //3.查看注册公司是不是名字重复了
           return Result.error(Messageconstant.ERROR_Company);
       }
        Fisco_accountLO fiscoAccount = Create_.create_fisco_account();
        CompanyInformationLO companyInformation = CompanyInformationLO.builder()
                .account(StringByString(companyRegisterDTO.getUser_account() + companyRegisterDTO.getName()))
                .password(Create_.create_hash256(fiscoAccount.getAccountAddress()+companyRegisterDTO.getPassword()))
                .companyAccountPrivate(fiscoAccount.getHexPrivateKey())
                .companyAccountAddress(fiscoAccount.getAccountAddress())
                .name(companyRegisterDTO.getName())
                .registerAccount(companyRegisterDTO.getUser_account())
                .registerId(context.getCurrtId())
                .companyCreateDate(companyRegisterDTO.getCompany_create_date())
                .phone(companyRegisterDTO.getPhone())
                .UnifiedSocialCreditCode(companyRegisterDTO.getUnified_social_credit_code())
                .companyBusiness(companyRegisterDTO.getCompany_business())
                .companyIntroduce(companyRegisterDTO.getCompany_introduce())
                .companyAddress(companyRegisterDTO.getCompany_address())
                .companyEmail(companyRegisterDTO.getCompany_email())
                .build();
        companyMapper.Insert(companyInformation);
        companyInformation = companyMapper.select(companyInformation);
        String registerHash = CompanyInfo_tools.insert(CompanyInfo.load(contractAddress.CompanyInfoAddress, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair()), companyInformation);

        //将该用户改为注册用户
        UserInformation.setAccountRole(2);
        userMapper.update(UserInformation);
        String update = UserInfo_tools.update(UserInfo.load(contractAddress.InfoAddress, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair()), UserInformation);
        //返回注册完成后哈希值
        return Result.sucess(RegisterVO.builder().ReisterHash(registerHash).Account(companyInformation.getAccount()).updateUserHash(update).build());
    }

    /**
     * 公司账号登录
     * @param companyLoginDTO
     * @return
     */
    @Override
    public Result<CompanyLoginVo> Login(CompanyLoginDTO companyLoginDTO) {
        CompanyInformationLO companyInformation = CompanyInformationLO.builder().account(companyLoginDTO.getAccount()).build();
        CompanyInformationLO select = companyMapper.select(companyInformation);
        if(!select.getPassword().equals(Create_.create_hash256(select.getCompanyAccountAddress()+companyLoginDTO.getPassword())) ){
            log.error(select.getCompanyAccountAddress());
            log.error(Create_.create_hash256(select.getCompanyAccountAddress()+companyLoginDTO.getPassword()));
            return  Result.error(Messageconstant.PASSWORD_ERROR);
        }
        //数据库审核通过
        FiscoLO fiscoSdk = Create_.create_fisco_sdk(select.getCompanyAccountPrivate());
        CompanyInfo company = CompanyInfo.load(contractAddress.CompanyInfoAddress, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair());
        try {
            CompanyInfo.Struct0 select1 = company.select(select.getId());
            if(select1.account.equals(companyLoginDTO.getAccount()) && select1.password.equals(Create_.create_hash256(select.getCompanyAccountAddress()+companyLoginDTO.getPassword()))){
                return Result.sucess(CompanyLoginVo.builder().companyName(select1.name).token(select1.account).build());
            }else{
                return Result.error(Messageconstant.NOSynchronization);
            }
        } catch (ContractException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Result<IpoVO> processIpo(CompanyIpoDTO companyIpoDTO) throws ContractException {
        CompanyInformationLO    CompanyInformation = CompanyInformationLO.builder()
                .account(context.getCurrtId())
                .UnifiedSocialCreditCode(companyIpoDTO.getUnifiedSocialCreditCode())
                .name(companyIpoDTO.getCompanyName())
                .build();
        CompanyInformation= companyMapper.select(CompanyInformation);
        if (CompanyInformation == null){
            return  Result.error(Messageconstant.Error_register);
        }
        // 定义合法的货币类型
        Set<String> validCurrencies = Set.of("CNY", "HKD", "MOP", "USD", "GBP", "EUR", "JPY", "SGD", "AUD");
        // 在此核验信息  核验货币类型
        String offeringType = companyIpoDTO.getOffering_type();
        //在此核验信息  核验货币类型
        if(offeringType ==null || !validCurrencies.contains(offeringType)){
            return  Result.error(Messageconstant.money_error);
        }
        //TODO : 上市地点未完成
        CompanyGoesLO companyGoesLO = CompanyGoesLO.builder()
                .UnifiedSocialCreditCode(companyIpoDTO.getUnifiedSocialCreditCode())
                .registeredCapital(companyIpoDTO.getRegisteredCapital())
                .offeringNumber(companyIpoDTO.getOfferingNumber())
                .totalShares(companyIpoDTO.getTotalShares())
                .offeringPrice(companyIpoDTO.getOfferingPrice())
                .companyName(companyIpoDTO.getCompanyName())
                .offeringAddress(companyIpoDTO.getOffering_address())
                .offeringType(companyIpoDTO.getOffering_type())
                .status(1)
                .build();
        // 添加信息到数据库里面
        companyGoesMapper.insert(companyGoesLO);
        //查询公司的创始人
        UserInformationLO userInformationLO = UserInformationLO.builder()
                .account(CompanyInformation.getRegisterAccount())
                .id(CompanyInformation.getRegisterId())
                .build();
        userInformationLO = userMapper.select_user(userInformationLO);
        EquityStructureTableLO equityStructureTableLOBuilder = EquityStructureTableLO.builder()
                .unifiedSocialCreditCode(companyIpoDTO.getUnifiedSocialCreditCode())
                .companyName(companyIpoDTO.getCompanyName())
                .ShareholderAccount(userInformationLO.getAccount())
                .Shareholder(userInformationLO.getName())
                .ShareholderNumber(companyIpoDTO.getTotalShares())
                .offeringType(companyIpoDTO.getOffering_type())
                .build();
        equityStructureMapper.insert(equityStructureTableLOBuilder);

        CompanyGoesLOS CompanyGoesLOs  = companyGoesMapper.select(companyGoesLO);
        equityStructureTableLOBuilder =  equityStructureMapper.select(equityStructureTableLOBuilder);
        FiscoLO fiscoSdk = Create_.create_fisco_sdk(CompanyInformation.getCompanyAccountPrivate());
        TransactionReceipt  CompanyGoesTGtableInsert = CompanyGoesTGtable_tools.insert(contractAddress.CompanyGoesTable, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair(),CompanyGoesLOs);
        TransactionReceipt TransactionReceiptinsert = EquityStructureTable_tools.insert(contractAddress.EquityStructureTable, fiscoSdk.getClient(), fiscoSdk.getCryptoKeyPair(), equityStructureTableLOBuilder);
        //创建一个股票挂起交易信息
        pendingStockOrdersLO build = pendingStockOrdersLO.builder()
                .companyName(companyIpoDTO.getCompanyName())
                .accountTrading(CompanyInformation.getRegisterAccount())
                .tradingType(1)
                .status(2)
                .companyStatus(true)
                .tradingNumber(companyIpoDTO.getOfferingPrice())
                .number(companyIpoDTO.getOfferingNumber())
                .build();
        pendingStockOrdersMapper.insert(build);
        return Result.sucess(IpoVO.builder().GoesHash(CompanyGoesTGtableInsert.getTransactionHash()).EquityHash(TransactionReceiptinsert.getTransactionHash()).build());
    }

    private   String StringByString(String data) {
       String account=  Create_.create_hash256(data).substring(26,42);
        if(companyMapper.select_number(CompanyInformationLO.builder().account(account).build())  != 0){
            StringByString(account);
            return account;
        }
        return account;
    }
}
